from __future__ import annotations

import re
from pathlib import Path
from datetime import datetime


def build_submission_map(repo_root: Path) -> dict[str, dict[str, str]]:
    assignments = [
        {
            "dir": "第一次作业",
            "label": "第一次作业",
            "file_patterns": [re.compile(r"^第一次课作业[-_](?P<name>.+)\.md$", re.IGNORECASE)],
            "dir_patterns": [],
        },
        {
            "dir": "第二次作业",
            "label": "第二次作业",
            "file_patterns": [re.compile(r"^第二次作业[-_](?P<name>.+)\.md$", re.IGNORECASE)],
            "dir_patterns": [re.compile(r"^第二次作业[-_](?P<name>.+)$", re.IGNORECASE)],
        },
        {
            "dir": "第三次作业",
            "label": "第三次作业",
            "file_patterns": [re.compile(r"^第三次作业[-_](?P<name>.+)\.md$", re.IGNORECASE)],
            "dir_patterns": [re.compile(r"^第三次作业[-_](?P<name>.+)$", re.IGNORECASE)],
        },
    ]

    submission_map: dict[str, dict[str, str]] = {}

    for a in assignments:
        base = repo_root / a["dir"]
        if not base.exists():
            continue
        for p in base.rglob("*.md"):
            name: str | None = None

            # 1) 从文件名匹配
            for pat in a["file_patterns"]:
                m = pat.match(p.name)
                if m:
                    name = m.group("name").strip()
                    break

            # 2) 若文件名不匹配，尝试从上级目录名匹配（适配 形如 第二次作业_姓名/第二次作业_姓名.md）
            if name is None:
                for dpat in a["dir_patterns"]:
                    dm = dpat.match(p.parent.name)
                    if dm:
                        name = dm.group("name").strip()
                        break

            if not name:
                continue

            rel = p.relative_to(repo_root).as_posix()
            entry = submission_map.setdefault(name, {})
            entry[a["label"]] = rel

        # 3) 若该作业以目录为单位提交（如 第三次作业_姓名），尝试直接识别目录
        for child in base.iterdir() if base.exists() else []:
            if not child.is_dir():
                continue
            name: str | None = None
            for dpat in a["dir_patterns"]:
                dm = dpat.match(child.name)
                if dm:
                    name = dm.group("name").strip()
                    break
            if not name:
                continue
            rel = child.relative_to(repo_root).as_posix()
            entry = submission_map.setdefault(name, {})
            # 不覆盖已有的更具体文件链接
            entry.setdefault(a["label"], rel)

    return submission_map


def render_markdown(submission_map: dict[str, dict[str, str]]) -> str:
    names = sorted(submission_map.keys())
    headers = ["姓名/代号", "第一次作业", "第二次作业", "第三次作业"]

    def link_or_cross(path: str | None) -> str:
        if path:
            return f"[✓]({path})"
        return "✗"

    lines: list[str] = []
    lines.append("# 提交统计")
    lines.append("")
    lines.append("| " + " | ".join(headers) + " |")
    lines.append("| " + " | ".join(["---"] * len(headers)) + " |")

    for name in names:
        first = submission_map[name].get("第一次作业")
        second = submission_map[name].get("第二次作业")
        third = submission_map[name].get("第三次作业")
        lines.append(f"| {name} | {link_or_cross(first)} | {link_or_cross(second)} | {link_or_cross(third)} |")

    lines.append("")
    lines.append(f"共 {len(names)} 人。自动生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    lines.append("")
    lines.append("生成方式：`python tools/generate_submissions.py`")
    lines.append("")
    return "\n".join(lines)


def render_table_only(submission_map: dict[str, dict[str, str]]) -> str:
    names = sorted(submission_map.keys())
    headers = ["姓名/代号", "第一次作业", "第二次作业", "第三次作业"]

    def link_or_cross(path: str | None) -> str:
        if path:
            return f"[✓]({path})"
        return "✗"

    lines: list[str] = []
    lines.append("| " + " | ".join(headers) + " |")
    lines.append("| " + " | ".join(["---"] * len(headers)) + " |")
    for name in names:
        first = submission_map[name].get("第一次作业")
        second = submission_map[name].get("第二次作业")
        third = submission_map[name].get("第三次作业")
        lines.append(f"| {name} | {link_or_cross(first)} | {link_or_cross(second)} | {link_or_cross(third)} |")
    return "\n".join(lines)


def update_readme_with_table(repo_root: Path, table_md: str, updated_at: str) -> None:
    readme_path = repo_root / "README.md"
    if not readme_path.exists():
        return
    content = readme_path.read_text(encoding="utf-8")

    start_tag = "<!-- submissions:start -->"
    end_tag = "<!-- submissions:end -->"
    block = f"{start_tag}\n最近更新：{updated_at}\n\n{table_md}\n{end_tag}"

    # 若已有块，直接替换
    pattern = re.compile(re.escape(start_tag) + r"[\s\S]*?" + re.escape(end_tag), re.MULTILINE)
    if pattern.search(content):
        new_content = pattern.sub(block, content)
        readme_path.write_text(new_content, encoding="utf-8")
        return

    # 定位“提交统计”章节范围
    sec_match = re.search(r"^##\s*提交统计\s*$", content, flags=re.MULTILINE)
    if sec_match:
        insert_pos = sec_match.end()
        next_sec = re.search(r"^##\s+", content[insert_pos:], flags=re.MULTILINE)
        if next_sec:
            insert_pos += next_sec.start()
        # 在章节末尾插入块
        new_content = content[:insert_pos].rstrip() + "\n\n" + block + "\n\n" + content[insert_pos:]
        readme_path.write_text(new_content, encoding="utf-8")
        return

    # 若没有该章节，则追加一个新章节
    addition = "\n\n## 提交统计（自动生成）\n\n" + block + "\n"
    readme_path.write_text(content.rstrip() + addition, encoding="utf-8")


def main() -> None:
    repo_root = Path(__file__).resolve().parents[1]
    submission_map = build_submission_map(repo_root)
    output_full = render_markdown(submission_map)
    (repo_root / "SUBMISSIONS.md").write_text(output_full, encoding="utf-8")

    table_only = render_table_only(submission_map)
    updated_at = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    update_readme_with_table(repo_root, table_only, updated_at)


if __name__ == "__main__":
    main()


